/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import { TPromise } from 'vs/base/common/winjs.base';
//import { isBoolean, isNumber } from 'vs/base/common/types';
import { Stream } from 'stream';
//import { parse as parseUrl } from 'url';
//import { assign } from 'vs/base/common/objects';
//import { createGunzip } from 'zlib';

export type Agent = any;

// export interface IRawRequestFunction {
// 	(options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
// }

export interface IRequestOptions {
	type?: string;
	url?: string;
	user?: string;
	password?: string;
	headers?: any;
	timeout?: number;
	data?: string | Stream;
	agent?: Agent;
	followRedirects?: number;
	strictSSL?: boolean;
	//getRawRequest?(options: IRequestOptions): IRawRequestFunction;
}

export interface IRequestContext {
	// req: http.ClientRequest;
	// res: http.ClientResponse;
	res: {
		headers: { [n: string]: string };
		statusCode?: number;
	};
	stream: Stream;
}

export interface IRequestFunction {
	(options: IRequestOptions): TPromise<IRequestContext>;
}

// async function getNodeRequest(options: IRequestOptions): TPromise<IRawRequestFunction> {
// 	const endpoint = parseUrl(options.url);
// 	const module = endpoint.protocol === 'https:' ? await import('https') : await import('http');
// 	return module.request;
// }

export function request(options: IRequestOptions): TPromise<IRequestContext> {
	debugger
	throw new Error("不支持");
	// let req: http.ClientRequest;

	// const rawRequestPromise = options.getRawRequest
	// 	? TPromise.as(options.getRawRequest(options))
	// 	: getNodeRequest(options);

	// return rawRequestPromise.then(rawRequest => {

	// 	return new TPromise<IRequestContext>((c, e) => {
	// 		const endpoint = parseUrl(options.url);

	// 		const opts: https.RequestOptions = {
	// 			hostname: endpoint.hostname,
	// 			port: endpoint.port ? parseInt(endpoint.port) : (endpoint.protocol === 'https:' ? 443 : 80),
	// 			protocol: endpoint.protocol,
	// 			path: endpoint.path,
	// 			method: options.type || 'GET',
	// 			headers: options.headers,
	// 			agent: options.agent,
	// 			rejectUnauthorized: isBoolean(options.strictSSL) ? options.strictSSL : true
	// 		};

	// 		if (options.user && options.password) {
	// 			opts.auth = options.user + ':' + options.password;
	// 		}

	// 		req = rawRequest(opts, (res: http.ClientResponse) => {
	// 			const followRedirects = isNumber(options.followRedirects) ? options.followRedirects : 3;
	// 			if (res.statusCode >= 300 && res.statusCode < 400 && followRedirects > 0 && res.headers['location']) {
	// 				request(assign({}, options, {
	// 					url: res.headers['location'],
	// 					followRedirects: followRedirects - 1
	// 				})).done(c, e);
	// 			} else {
	// 				let stream: Stream = res;

	// 				if (res.headers['content-encoding'] === 'gzip') {
	// 					stream = stream.pipe(createGunzip());
	// 				}

	// 				c({ res, stream });
	// 			}
	// 		});

	// 		req.on('error', e);

	// 		if (options.timeout) {
	// 			req.setTimeout(options.timeout);
	// 		}

	// 		if (options.data) {
	// 			if (typeof options.data === 'string') {
	// 				req.write(options.data);
	// 			} else {
	// 				options.data.pipe(req);
	// 				return;
	// 			}
	// 		}

	// 		req.end();
	// 	}, () => req && req.abort());
	// });
}

function isSuccess(context: IRequestContext): boolean {
	return (context.res.statusCode >= 200 && context.res.statusCode < 300) || context.res.statusCode === 1223;
}

function hasNoContent(context: IRequestContext): boolean {
	return context.res.statusCode === 204;
}

export function download(filePath: string, context: IRequestContext): TPromise<void> {
	debugger
	throw new Error("不支持");
	// return new TPromise<void>((c, e) => {
	// 	const out = createWriteStream(filePath);

	// 	out.once('finish', () => c(null));
	// 	context.stream.once('error', e);
	// 	context.stream.pipe(out);
	// });
}

export function asText(context: IRequestContext): TPromise<string> {
	return new TPromise((c, e) => {
		if (!isSuccess(context)) {
			return e('Server returned ' + context.res.statusCode);
		}

		if (hasNoContent(context)) {
			return c(null);
		}

		let buffer: string[] = [];
		context.stream.on('data', (d: string) => buffer.push(d));
		context.stream.on('end', () => c(buffer.join('')));
		context.stream.on('error', e);
	});
}

export function asJson<T>(context: IRequestContext): TPromise<T> {
	return new TPromise((c, e) => {
		if (!isSuccess(context)) {
			return e('Server returned ' + context.res.statusCode);
		}

		if (hasNoContent(context)) {
			return c(null);
		}

		const buffer: string[] = [];
		context.stream.on('data', (d: string) => buffer.push(d));
		context.stream.on('end', () => {
			try {
				c(JSON.parse(buffer.join('')));
			} catch (err) {
				e(err);
			}
		});
		context.stream.on('error', e);
	});
}
